#include "calculation_server.h"

class JobIdEquals{
	int i;
public:
	JobIdEquals(int i) : i(i) {}
	bool operator()(const shared_ptr<Job> job) const{
		return (*job).getJobID() == i;
	}
};
class JobComapre{
public:
	bool operator()(const shared_ptr<Job> job1,const shared_ptr<Job>job2) const{
		if((*job1).getPriority()==(*job2).getPriority()){
			return (*job1).getJobID()<(*job2).getJobID();
		}
		return (*job1).getPriority()>(*job2).getPriority();
	}
};

CalculationServer::CalculationServer(): jobList(),counter(0){}

int CalculationServer::addJob(JobType type, int priority, const Matrix& A,
		const Matrix& B){
	try{switch (type) {
		case SOLVE_EQUATION_SYSTEM:
			jobList.insert(shared_ptr<SolveEquationSystem>
			(new SolveEquationSystem(A,B,priority,++counter)),jobList.begin());
			break;
		case SIMILARITY:
			jobList.insert(shared_ptr<Similarity>
			(new Similarity(A,B,priority,++counter)),jobList.begin());
			break;
		case POLYNOMIAL:
			jobList.insert(shared_ptr<Polynomial>
			(new Polynomial(A,B,priority,++counter)),jobList.begin());
			break;
	}
	return counter;}catch (Job::InvalidPriority& e) {
		throw CalculationServer::InvalidPriority();
	}
}

void CalculationServer::removeJob(int jobID){
	try {
		Iterator<shared_ptr<Job> > iterator = jobList.find(JobIdEquals(jobID));
		jobList.remove(iterator);
	} catch (ListExceptions::ElementNotFound& e) {
		throw CalculationServer::JobNotFound();
	}
}

void CalculationServer::changePriority(int jobID,int newPriority){
	try {
		Iterator<shared_ptr<Job> > iterator = jobList.find(JobIdEquals(jobID));
		(*iterator)->changePriority(newPriority);
	} catch (ListExceptions::ElementNotFound& e1) {
		throw JobNotFound();
	} catch (Job::InvalidPriority& e2) {
		throw InvalidPriority();
	}
}

Matrix CalculationServer::execute(){
	Iterator<shared_ptr<Job> > iterator = jobList.find(JobIdEquals(nextJob()));
	try {
		Matrix matrix=(*iterator)->execute();
		jobList.remove(iterator);
		return matrix;
	}
	catch (MatrixExceptions::MatrixException& e1) {
		jobList.remove(iterator);
		throw OperationFailed();
	}
	catch (Job::OperationFailed& e2){
		jobList.remove(iterator);
		throw OperationFailed();
	}

}
int CalculationServer::nextJob(){
	try{
		List<shared_ptr<Job> > listToSort = jobList;
		listToSort.sort(JobComapre());
		return (*(listToSort.begin()))->getJobID();
	}catch(ListExceptions::ElementNotFound& e){
		throw JobNotFound();
	}

}
int CalculationServer::totalJobs(){
	return jobList.getSize();
}


